package future;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import util.Util;

import java.util.concurrent.*;

/**
 * @author yding5
 * @date 2021/9/25
 */
public class FutureTest {

    private static CountDownLatch COUNT_DOWN;
    private static ExecutorService EXECUTOR_SERVICE;

    @Before
    public void setup() {
        COUNT_DOWN = new CountDownLatch(3);
        EXECUTOR_SERVICE = Executors.newCachedThreadPool();
    }

    @After
    public void cleanup() {
        EXECUTOR_SERVICE.shutdownNow();
    }

    @Test
    public void test() throws InterruptedException {
        Util.timeWatch();
        Future<String> taskA = EXECUTOR_SERVICE.submit(() -> finishTaskA());
        Future<String> taskB = EXECUTOR_SERVICE.submit(() -> finishTaskB());
        String A = getFuture(taskA);
        String B = getFuture(taskB);
        Future<String> taskC = EXECUTOR_SERVICE.submit(() -> finishTaskC(A));
        String C = getFuture(taskC);
        COUNT_DOWN.await();
        Util.timeWatch();
    }

    private static String finishTaskA() {
        Util.sleep(100L);
        Util.print("finish task A.");
        COUNT_DOWN.countDown();
        return "A";
    }

    private static String finishTaskB() {
        Util.sleep(200L);
        Util.print("finish task B.");
        COUNT_DOWN.countDown();
        return "B";
    }

    private static String finishTaskC(String A) {
        Util.sleep(300L);
        Util.print("finish task C based on " + A);
        COUNT_DOWN.countDown();
        return "C";
    }

    public static <T> T getFuture(Future<T> future) {
        try {
            return future.get(1, TimeUnit.SECONDS);
        } catch (Exception e) {
            future.cancel(true);
        }
        return null;
    }
}
